package com.jay.tools.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Environment;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


/**
 * 图片处理
 */
@SuppressWarnings("deprecation")
public class BitmapUtil {

    private static final String TAG = "BtimapUtil";

    /**
     * 从指定路径加载图片，指定展示的图片宽高为屏幕的宽高
     *
     * @param context
     * @param filePath 文件路径
     */
    public static Bitmap getBitmapFromFilePath(Context context, String filePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        int bmpWidth = options.outWidth;
        int bmpHeght = options.outHeight;

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metrics);
        int screenWidth = metrics.widthPixels;
        int screenHeight = metrics.heightPixels;

        options.inSampleSize = 1;
        if (bmpWidth > bmpHeght) {
            if (bmpWidth > screenWidth)
                options.inSampleSize = bmpWidth / screenWidth;
        } else {
            if (bmpHeght > screenHeight)
                options.inSampleSize = bmpHeght / screenHeight;
        }
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

    /**
     * 从指定路径加载图片，展示的图片宽高为需求设定
     *
     * @param path   路径
     * @param width  指定的宽
     * @param height 指定的高
     * @return
     */
    public static Bitmap getBitmapFromFilePath(String path, int width, int height) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        // 不解析图片只是去解析图片头文件信息，拿到图片的宽度和高度
        BitmapFactory.decodeFile(path, opts);
        opts.inJustDecodeBounds = true;
        int imageWidth = opts.outWidth;
        int imageHeight = opts.outHeight;
        Log.d(TAG, "图片的宽：" + imageWidth + ",图片的高：" + imageHeight);
        // 拿到屏幕的缩放比
        int scaleX = imageWidth / width;
        int scaleY = imageHeight / height;
        int scale = 1;
        // 横屏显示时
        if (scaleX > scaleY && scaleY >= 1) {
            scale = scaleX;
        }
        // 竖屏显示时
        if (scaleY > scaleX && scaleX >= 1) {
            scale = scaleY;
        }
        // 开始真正的解析图片
        opts.inJustDecodeBounds = false;
        // 采样率
        opts.inSampleSize = scale;
        return BitmapFactory.decodeFile(path, opts);
    }

    /**
     * Bitmap to File
     *
     * @param bitmap
     */
    public static String bitmap2File(Bitmap bitmap) {

        File outDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        if (!outDir.exists()) {
            outDir.mkdirs();
        }
        File outFile = new File(outDir, System.currentTimeMillis() + ".jpg");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(outFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 40, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return outFile.getAbsolutePath();
    }

    /**
     * 把Bitmap转Byte
     */
    public static byte[] bitmap2Bytes(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * 根据网址获得图片，优先从本地获取，本地没有则从网络下载
     *
     * @param url       图片网址
     * @param context
     * @param reqHeight
     * @param reqWidth
     * @return
     */
    public static Bitmap getBitmap(String url, Context context, int reqHeight, int reqWidth) {
        String imageName = url.substring(url.lastIndexOf("/") + 1, url.length());
        File file = new File(getPath(context), imageName);
        if (file.exists()) {
            // Log.d(TAG+"local", "图片URL= " + url+"，图片名："+imageName);
            Bitmap bitmap = FileBitmap(imageName, file.getPath(), reqHeight, reqWidth);
            return bitmap;
        } else {
            // Log.d(TAG+"net", "图片URL= " + url+"，图片名："+imageName);
            Bitmap netBitmap = getNetBitmap(url, file, context, reqHeight, reqWidth);
            return netBitmap;
        }
    }

    /**
     * 图片压缩处理
     *
     * @param imageName
     * @param imagePath
     * @param reqHeight
     * @param reqWidth
     * @return
     */
    private static Bitmap FileBitmap(String imageName, String imagePath, int reqHeight, int reqWidth) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, options);
        options.inDither = false;// 不进行图片抖动处理

        options.inPreferredConfig = null; // 默认是Bitmap.Config.ARGB_8888
        /* 下面两个字段需要组合使用 */
        options.inPurgeable = true;// true当系统内存不足时会回收
        options.inInputShareable = true;

        options.inSampleSize = getInSampleSize(options, reqHeight, reqWidth);
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
        return bitmap;
    }

    /**
     * 网络可用状态下，下载图片并保存在本地
     *
     * @param netUrl    图片网址
     * @param file      本地保存的图片文件
     * @param context
     * @param reqHeight
     * @param reqWidth
     * @return
     */
    private static Bitmap getNetBitmap(String netUrl, File file, Context context,
                                       int reqHeight, int reqWidth) {
        Log.d(TAG, "getBitmap from net");
        Bitmap bitmap = null;
        try {
            URL url = new URL(netUrl);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setDoInput(true);
            con.connect();
            InputStream in = con.getInputStream();
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inDither = false;// 不进行图片抖动处理
            options.inPreferredConfig = null;// 设置让解码器以最佳方式解码
            options.inPurgeable = true;// true当系统内存不足时会回收
            options.inInputShareable = true;
            options.inSampleSize = getNetSampleSize(netUrl, context,
                    reqHeight, reqWidth);// 图片长宽方向缩小倍数
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeStream(in, null, options);
            FileOutputStream out = new FileOutputStream(file.getPath());
            if (bitmap != null)
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
            in.close();
            return bitmap;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
        return null;
    }

    private static int getNetSampleSize(String strUrl,
                                        Context context, int reqHeight, int reqWidth) {
        try {
            URL url = new URL(strUrl);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setDoInput(true);
            con.connect();
            InputStream in = con.getInputStream();
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, options);
            in.close();
            return getInSampleSize(options, reqHeight, reqWidth);// 图片长宽方向缩小倍数
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取缩放比
     *
     * @param options
     * @param reqHeight
     * @param reqWidth
     * @return
     */
    private static int getInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // 计算出实际宽高和目标宽高的比率
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            // 选择宽和高中最小的比率作为inSampleSize的值，这样可以保证最终图片的宽和高
            // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        // System.out.println("缩小倍数：" + inSampleSize+"高："+height+",宽"+width);
        return inSampleSize;
    }

    /**
     * 根据传入的list中保存的图片网址，获取相应的图片列表
     *
     * @param list      保存图片网址的列表
     * @param context
     * @param reqHeight
     * @param reqWidth
     * @return
     */
    public static List<Bitmap> getBitmap(List<String> list, Context context, int reqHeight,
                                         int reqWidth) {
        List<Bitmap> result = new ArrayList<Bitmap>();
        for (String strUrl : list) {
            Bitmap bitmap = getBitmap(strUrl, context, reqHeight, reqWidth);
            if (bitmap != null) {
                result.add(bitmap);
            }
        }
        return result;
    }

    /**
     * 获取图片的存储目录，在有sd卡的情况下为 “/sdcard/apps_images/本应用包名/cach/images/”
     * 没有sd的情况下为“/data/data/本应用包名/cach/images/”
     *
     * @param context 上下文
     * @return 本地图片存储目录
     */
    private static String getPath(Context context) {
        boolean hasSDCard = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        String packageName = context.getPackageName() + "/cach/images/";
        String path = null;
        if (hasSDCard) {
            path = "/sdcard/apps_images/" + packageName;
        } else {
            path = "/data/data/" + packageName;
        }
        File file = new File(path);
        boolean isExist = file.exists();
        if (!isExist) {
            file.mkdirs();
        }
        return file.getPath();
    }

    /**
     * 图片超过一定空间后进行缩放
     *
     * @param bitmap
     */
    public static void imageZoom(Bitmap bitmap) {
        // 图片允许最大空间 单位：KB
        double maxSize = 400.00;
        // 将bitmap放至数组中，意在bitmap的大小（与实际读取的原文件要大）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] b = baos.toByteArray();
        // 将字节换成KB
        double mid = b.length / 1024;
        // 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
        if (mid > maxSize) {
            // 获取bitmap大小 是允许最大大小的多少倍
            double i = mid / maxSize;
            // 开始压缩 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
            // （1.保持刻度和高度和原bitmap比率一致，压缩后也达到了最大大小占用空间的大小）
            bitmap = zoomImage(bitmap, bitmap.getWidth() / Math.sqrt(i),
                    bitmap.getHeight() / Math.sqrt(i));
        }
    }

    /**
     * 图片的缩放方法
     *
     * @param bgimage   原图片资源
     * @param newWidth  缩放后宽度
     * @param newHeight 缩放后高度
     * @return
     */
    public static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
        if (bgimage == null)
            return null;
        // 获取这个图片的宽和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 计算宽高缩放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放图片动作
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true);
    }

    /**
     * 通过文件路径获取到bitmap
     *
     * @param path
     * @param w
     * @param h
     * @return
     */
    public static Bitmap getBitmapFromPath(String path, int w, int h) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        // 设置为ture只获取图片大小
        opts.inJustDecodeBounds = true;
        opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
        // 返回为空
        BitmapFactory.decodeFile(path, opts);
        int width = opts.outWidth;
        int height = opts.outHeight;
        float scaleWidth = 0.f, scaleHeight = 0.f;
        if (width > w || height > h) {
            // 缩放
            scaleWidth = ((float) width) / w;
            scaleHeight = ((float) height) / h;
        }
        opts.inJustDecodeBounds = false;
        float scale = Math.max(scaleWidth, scaleHeight);
        opts.inSampleSize = (int) scale;
        WeakReference<Bitmap> weak = new WeakReference<Bitmap>(BitmapFactory.decodeFile(path, opts));
        return Bitmap.createScaledBitmap(weak.get(), w, h, true);
    }

    /**
     * 把bitmap转换成base64
     *
     * @param bitmap
     * @param bitmapQuality
     * @return
     */
    public static String getBase64FromBitmap(Bitmap bitmap, int bitmapQuality) {
        ByteArrayOutputStream bStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, bitmapQuality, bStream);
        byte[] bytes = bStream.toByteArray();
        return Base64.encodeToString(bytes, Base64.DEFAULT);
    }

    /**
     * 把base64转换成bitmap
     *
     * @param string
     * @return
     */
    public static Bitmap getBitmapFromBase64(String string) {
        byte[] bitmapArray = null;
        try {
            bitmapArray = Base64.decode(string, Base64.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
    }

}
